package tags

import (
	"gitee.com/theegg/go-brick/app/model"
	"gitee.com/theegg/go-brick/app/model/content/tag_nodes"
	"gitee.com/theegg/go-brick/app/service/app"
	"gitee.com/theegg/go-brick/app/service/help/cmd5"
	"gitee.com/theegg/go-brick/app/service/help/cslice"
	"regexp"
	"strings"
)

// 查询参数
type TagQueryParams struct {
	PageSize  string `form:"page_size"  binding:"gte=0,lte=100" label:"每页数量"`
	PageIndex string `form:"page_index"  binding:"gte=0,lte=99999" label:"当前页数"`
	TagTitle  string `form:"tag_title"  binding:"" label:"标题"`
}

// 添加参数
type TagAddParams struct {
	TagTitle string `form:"tag_title"  binding:"required,CustomPlainText=6 18" label:"Tag标题"`
}

var SingleTagMaxLength = 18
var SingleTagMinLength = 6

// 分页获取所有数据
// @param params map 参数
// @return interface{}, error
func GetDataList(params map[string]interface{}) (map[string]interface{}, error) {
	returnData := make(map[string]interface{}, 0)

	queryParams, errBuild := model.BuildAdminQueryParam(params)
	if errBuild != nil {
		return nil, app.NewError(errBuild)
	}

	query := app.Db().Limit(queryParams.Limit, queryParams.Offset)

	// query title
	if _, ok := queryParams.Params["title"]; ok && queryParams.Params["title"] != "" {
		query.Where("tag_title like ?", "%"+queryParams.Params["title"].(string)+"%")
	}

	data := make([]*Tags, 0)

	// 求总条数
	total, err := query.FindAndCount(&data)
	if err != nil {
		return nil, app.NewError(err)
	}

	returnData["data"] = data
	returnData["total"] = total

	return returnData, nil
}

// @title AddTagsToNode
// @description 添加tag到node
func AddTagsToNode(tags []string, nodeId int64, authorId int64) ([]int64, error) {
	// x. 判断哪些是新tag, 已经存在的略过，新的插入数据库
	// y. 判断当前node 哪些tag是增加的(邦定)，哪些是减少的(解邦)

	// 1. 获取tag md5值, 去除空格
	tagsMd5Arr := make(map[string]string)
	for _, tagName := range tags {
		tagsMd5Arr[cmd5.MustEncryptString(strings.TrimSpace(tagName))] = strings.TrimSpace(tagName)
	}

	// 2. 判断哪些是新增，　哪些已经存在
	existTagIds := make([]int64, 0)
	newTags := make([]*Tags, 0)

	for tagSign, tagName := range tagsMd5Arr {
		item, err := GetItemBySign(tagSign)
		if err != nil {
			return nil, app.NewError(err)
		}

		if item == nil {
			tmpTag := new(Tags)
			tmpTag.TagSign = tagSign
			tmpTag.TagTitle = tagName
			tmpTag.AuthorId = authorId
			newTags = append(newTags, tmpTag)
		} else {
			existTagIds = append(existTagIds, item.Id)
		}
	}

	// 3. 保存新增的tag
	if len(newTags) > 0 {
		for _, item := range newTags {
			affected, err := app.Db().Insert(item)
			if err != nil {
				return nil, err
			}

			if int(affected) != len(newTags) {
				return nil, app.NewError("对不起, 生成数量不正确")
			}

			existTagIds = append(existTagIds, item.Id)
		}
	}

	// 4. 因为node可能是更新, 需要获取node原来已经有的tags
	var nodeHasTagsIds []int64
	err := app.Db().Table("tag_nodes").Cols("id").Where("node_id = ?", nodeId).Find(&nodeHasTagsIds)
	if err != nil {
		return nil, app.NewError(err)
	}

	// 5. 获取哪些是 node 新增的tags
	removeIds := cslice.Int64SliceMainDiff(nodeHasTagsIds, existTagIds)

	tagNodes := new(tag_nodes.TagNodes)
	affected, err := app.Db().In("id", removeIds).Delete(tagNodes)
	if err != nil {
		return nil, app.NewError(err)
	}

	if int(affected) != len(removeIds) {
		return nil, app.NewError("对不起，解除tag绑定数量有误")
	}

	// 6. 获取哪些是 node 新增的tags
	newIds := cslice.Int64SliceMainDiff(existTagIds, nodeHasTagsIds)

	if len(newIds) > 0 {
		tagNodeBinds := make([]tag_nodes.TagNodes, 0)
		for _, id := range newIds {
			tagNodeBinds = append(tagNodeBinds, tag_nodes.TagNodes{
				NodeId: nodeId,
				TagId:  id,
			})
		}

		affectedBind, err := app.Db().Insert(&tagNodeBinds)
		if err != nil {
			return nil, app.NewError(err)
		}

		if affectedBind != int64(len(tagNodeBinds)) {
			return nil, app.NewError("对不起, tag数量绑定不正确不正确")
		}
	}

	return existTagIds, nil
}

// @param sign string 数据的id
// @return *Tags, error
func GetItemBySign(sign string) (*Tags, error) {
	item := new(Tags)
	has, err := app.Db().Where("tag_sign = ?", sign).Get(item)

	if err != nil {
		return nil, err
	}

	if !has {
		return nil, nil
	}

	return item, nil
}

// @title GetTagsByNodeId
// @description 获取所有的tags
// @return []*tag_nodes.TagNodes
func GetTagsByNodeId(nodeId int64) ([]*Tags, error) {
	var tagIds []int64
	err := app.Db().Table("tag_nodes").Cols("tag_id").Where("node_id = ?", nodeId).Find(&tagIds)

	if err != nil {
		return nil, err
	}

	// 为空
	if len(tagIds) == 0 {
		return []*Tags{}, nil
	}

	// 后去所有标签
	tags := make([]*Tags, 0)
	errTags := app.Db().In("id", tagIds).Find(&tags)
	if errTags != nil {
		return nil, errTags
	}

	return tags, nil
}

// @title CheckTag
// @description 检查tag
func CheckTag(tag string) bool {
	if len(tag) > SingleTagMaxLength || len(tag) < SingleTagMinLength {
		return false
	}

	res, err := regexp.MatchString(`^[,_\-A-Za-z0-9\p{Han}]+$`, tag)
	if err != nil {
		return false
	}

	if !res {
		return false
	}

	return true
}
